import type React from 'react';
import { useCallback, useEffect, useRef } from 'react';
import type { Point2D, Vector2D } from '../../types';
import styles from './MatrixCanvas.module.less';

interface MatrixCanvasProps {
  width: number;
  height: number;
  points: Point2D[];
  vectors: Vector2D[];
  transformedPoints: Point2D[];
  transformedVectors: Vector2D[];
  transformOrigin: Point2D;
  transformedOrigin: Point2D;
  onAddPoint: (x: number, y: number) => void;
  onSetTransformOrigin: (x: number, y: number) => void;
}

export const MatrixCanvas: React.FC<MatrixCanvasProps> = ({
  width,
  height,
  points,
  vectors,
  transformedPoints,
  transformedVectors,
  transformOrigin,
  transformedOrigin,
  onAddPoint,
  onSetTransformOrigin,
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  const handleCanvasClick = useCallback(
    (event: React.MouseEvent<HTMLCanvasElement>) => {
      const canvas = event.currentTarget;
      const rect = canvas.getBoundingClientRect();
      const x = event.clientX - rect.left - width / 2;
      // 反转y坐标，使y轴向上为正方向
      const y = -(event.clientY - rect.top - height / 2);

      if (event.shiftKey) {
        // Shift+点击设置变换原点
        onSetTransformOrigin(x, y);
      } else {
        // 普通点击添加点
        onAddPoint(x, y);
      }
    },
    [width, height, onAddPoint, onSetTransformOrigin],
  );

  // 绘制箭头的辅助函数
  // 注意：由于y轴方向已改为向上，箭头绘制会自动适应新的坐标系
  const drawArrow = useCallback(
    (
      ctx: CanvasRenderingContext2D,
      fromX: number,
      fromY: number,
      toX: number,
      toY: number,
      color: string,
      lineWidth: number,
    ) => {
      const headLength = 10;
      const dx = toX - fromX;
      const dy = toY - fromY;
      const angle = Math.atan2(dy, dx);

      // 绘制线条
      ctx.strokeStyle = color;
      ctx.lineWidth = lineWidth;
      ctx.beginPath();
      ctx.moveTo(fromX, fromY);
      ctx.lineTo(toX, toY);
      ctx.stroke();

      // 绘制箭头
      ctx.fillStyle = color;
      ctx.beginPath();
      ctx.moveTo(toX, toY);
      ctx.lineTo(
        toX - headLength * Math.cos(angle - Math.PI / 6),
        toY - headLength * Math.sin(angle - Math.PI / 6),
      );
      ctx.lineTo(
        toX - headLength * Math.cos(angle + Math.PI / 6),
        toY - headLength * Math.sin(angle + Math.PI / 6),
      );
      ctx.closePath();
      ctx.fill();
    },
    [],
  );

  // Canvas绘图逻辑
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    // 清空画布
    ctx.clearRect(0, 0, width, height);

    // 绘制坐标系
    ctx.strokeStyle = '#ccc';
    ctx.lineWidth = 1;

    // 绘制Y轴
    ctx.beginPath();
    ctx.moveTo(width / 2, 0);
    ctx.lineTo(width / 2, height);
    ctx.stroke();

    // 绘制X轴
    ctx.beginPath();
    ctx.moveTo(0, height / 2);
    ctx.lineTo(width, height / 2);
    ctx.stroke();

    // 绘制X轴箭头
    drawArrow(ctx, width - 20, height / 2, width - 5, height / 2, '#ccc', 1);

    // 绘制Y轴箭头（向上）
    drawArrow(ctx, width / 2, 20, width / 2, 5, '#ccc', 1);

    // 绘制坐标轴标签
    ctx.fillStyle = '#666';
    ctx.font = '12px Arial';
    ctx.fillText('X', width - 15, height / 2 - 10);
    ctx.fillText('Y', width / 2 + 10, 15);

    // 绘制原始点
    points.forEach((point) => {
      ctx.fillStyle = 'blue';
      ctx.beginPath();
      // 反转y坐标，使y轴向上为正方向
      ctx.arc(point.x + width / 2, -point.y + height / 2, 4, 0, 2 * Math.PI);
      ctx.fill();
    });

    // 绘制变换后的点
    transformedPoints.forEach((point) => {
      ctx.fillStyle = 'red';
      ctx.beginPath();
      // 反转y坐标，使y轴向上为正方向
      ctx.arc(point.x + width / 2, -point.y + height / 2, 4, 0, 2 * Math.PI);
      ctx.fill();
    });

    // 绘制原始向量
    vectors.forEach((vector) => {
      const startX = width / 2;
      const startY = height / 2;
      const endX = startX + vector.x;
      // 反转y坐标，使y轴向上为正方向
      const endY = startY - vector.y;

      drawArrow(ctx, startX, startY, endX, endY, 'green', 2);
    });

    // 绘制变换后的向量
    transformedVectors.forEach((vector) => {
      // 反转y坐标，使y轴向上为正方向
      const startX = width / 2 + transformedOrigin.x;
      const startY = height / 2 - transformedOrigin.y;
      const endX = startX + vector.x;
      const endY = startY - vector.y;

      drawArrow(ctx, startX, startY, endX, endY, 'orange', 2);
    });

    // 绘制变换原点
    ctx.fillStyle = 'purple';
    ctx.strokeStyle = 'white';
    ctx.lineWidth = 2;
    ctx.beginPath();
    // 反转y坐标，使y轴向上为正方向
    ctx.arc(
      transformOrigin.x + width / 2,
      -transformOrigin.y + height / 2,
      6,
      0,
      2 * Math.PI,
    );
    ctx.fill();
    ctx.stroke();

    // 绘制变换后的原点
    ctx.fillStyle = 'magenta';
    ctx.beginPath();
    // 反转y坐标，使y轴向上为正方向
    ctx.arc(
      transformedOrigin.x + width / 2,
      -transformedOrigin.y + height / 2,
      6,
      0,
      2 * Math.PI,
    );
    ctx.fill();
    ctx.stroke();
  }, [
    width,
    height,
    points,
    vectors,
    transformedPoints,
    transformedVectors,
    transformOrigin,
    transformedOrigin,
    drawArrow,
  ]);

  return (
    <div className={styles.container}>
      <canvas
        ref={canvasRef}
        className={styles.canvas}
        width={width}
        height={height}
        onClick={handleCanvasClick}
      />
      <div className={styles.instructions}>
        点击添加点，Shift+点击设置变换原点
      </div>
    </div>
  );
};
